package com.github.butid.data.netty.handler;

import com.github.butid.data.codec.RequestBody;
import com.github.butid.data.netty.core.Command;
import com.github.butid.data.netty.event.EventDispatcher;
import com.github.butid.data.netty.exception.CommandMultiException;
import com.github.butid.data.netty.exception.CommandNotFoundException;
import com.github.butid.data.netty.springboot.SpringContext;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 消息接收处理
 * Created By wangjing.dc@qq.com On 2020/8/10
 **/
@Slf4j
public class CommandDispacherHandler extends SimpleChannelInboundHandler<RequestBody> {

    private static final int MIN_PACKAGE_SIZE = 8;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RequestBody request) throws Exception {
        log.debug("处理远端[{}]消息", ctx.channel().remoteAddress());

        List<Command> cmds = SpringContext.findBeans(request.getCmdType(), request.getCmdCode());

        // Command不存在
        if(cmds.size() <= 0){
            throw new CommandNotFoundException(
                    String.format("[cmdType=%s,cmdCode=%s]",request.getCmdType() , request.getCmdCode()));
        }
        // Command定义超过一个
        if(cmds.size() > 1){
            throw new CommandMultiException(cmds.toString());
        }


        try{
            ctx.writeAndFlush(cmds.get(0).exec(request));
        }catch (Exception e){
            ctx.fireExceptionCaught(e);
        }

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        log.debug("接受自远端连接:{}", ctx.channel().remoteAddress());
        EventDispatcher.dispatchChannelActiveEvent(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.debug("远端连接关闭:{}", ctx.channel().remoteAddress());
        EventDispatcher.dispatchChannelInactiveEvent(ctx);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            log.debug("远端连接超时, 状态:{}, 地址:{}", event.state(), ctx.channel().remoteAddress());

            switch (event.state()) {
                case READER_IDLE:
                    EventDispatcher.dispatchReaderIdleEvent(ctx);
                    break;
                case WRITER_IDLE:
                    EventDispatcher.dispatchWriterIdleEvent(ctx);
                    break;
                case ALL_IDLE:
                    EventDispatcher.dispatchAllIdleEvent(ctx);
                    break;
                default:
                    EventDispatcher.dispatchUnknowEvent(ctx);
                    break;
            }
        } else {
            EventDispatcher.dispatchUnknowEvent(ctx);
        }
        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.debug("远端连接发生异常:{}", ctx.channel().remoteAddress(), cause);
        EventDispatcher.dispatchExceptionEvent(ctx, cause);
    }


}